/**
 * Created with IntelliJ IDEA.
 * User: bcw
 * Date: 13-12-24
 * Time: 下午2:05
 * To change this template use File | Settings | File Templates.
 */

(function(Raphael) {
    Raphael.el.appendTransform = function(transform) {
        return this.transform(this.transform().toString() + transform);
    }

    /**
     * Function to create SvgCanvas object.
     */
    Raphael.svgCanvas = function(paper, options) {
        return new SvgCanvas(paper, options);
    }

    // Current version.
    Raphael.svgCanvas.VERSION = '0.5.1';

    /**
     * The Sketchpad object.
     */
    var SvgCanvas = function(paper, options) {
        // Use self to reduce confusion about this.
        var self = this;
        self.selectedElement = null;
        self.lastSelectedElement = null;
        var undoManager = new UndoManager();

        var _options = {
            width: 100,
            height: 100,
            strokes: [],
            editing: false
        };
        var _defaultAttr = {
            stroke: '#000000',
            fill:'#000000',
            'font-size':'22px',
            "stroke-width": 2
//            "stroke-opacity": 1.0,
//            "stroke-linecap": "round",
//            "stroke-linejoin": "round"
        };
        jQuery.extend(_options, options);


        // The Raphael context to draw on.
        var _paper;
        var containerId;

        // The Raphael SVG canvas.
        var _canvas;
        // The HTML element that contains the canvas.
        var _container;

        self.reset = function() {
            undoManager.clear();
            for (layerName in _layers) {
                _layers[layerName].clear();
            }
            _paper.clear();
            self.changeTool("select");
        };

        self.setCanvasSize = function(width, height) {
            if (width == undefined || height == undefined) {
                return;
            }
            console.log("set canvas size width:", width, " height:", height);
            _paper.setSize(width, height);
            _paper.setViewBox(0, 0, width, height);
            _container.width(_paper.width);
            _container.height(_paper.height);
            $('#canvasBackground').width(_paper.width);
            $('#canvasBackground').height(_paper.height);

            var $areaCanvas = _container.parent();
            var areaCanvasWidth = $areaCanvas.width();
            var areaCanvasHeight = $areaCanvas.height();
            if (areaCanvasWidth < _paper.width + 100) {
                $areaCanvas.width(_paper.width + 100);
            }
            if (areaCanvasHeight < _paper.height + 100) {
                $areaCanvas.height(_paper.height + 100);
            }

            var paddingTop = ($areaCanvas.height() - _paper.height) / 2;
            _container.css("top", paddingTop + "px");
            // 滚动居中
            $areaCanvas.parent().scrollLeft(($areaCanvas.width() - $areaCanvas.parent().width()) / 2);
            $areaCanvas.parent().scrollTop(($areaCanvas.height() - $areaCanvas.parent().height()) / 2);
        };


        // create
        if (paper.raphael && paper.raphael.constructor == Raphael.constructor) {
            _paper = paper;
        } else if (typeof paper == "string") {// todo: 自定义长度
            //var grid = Raphael(paper, _options.width, _options.height);
            containerId = paper;
            _paper = Raphael(containerId, _options.width, _options.height);
            _canvas = _paper.canvas;
            _container = $(_canvas).parent();
            self.setCanvasSize(_options.width, _options.height);
        } else {
            throw "first argument must be a Raphael object, an element ID, an array with 3 elements";
        }

        // 键盘事件处理
        $(document).keypress(function( event ) {
            console.log( event.type + ": " +  event.which );
        });
        $(document).keyup(function( event ) {
            console.log( event.type + ": " +  event.which );
            var el = self.getSelected();
            if (el) {
                self.initFreeTransform(el);
            }
            if (event.which == 27) {// esc
                if(_pen != null && typeof(_pen.abort) == 'function') {
                    _pen.abort();
                }
            } else if (event.which == 90) {//Z
                if (event.ctrlKey) {
                    self.undo();
                }
            } else if (event.which == 82) {//R
                if (event.ctrlKey) {
                    self.redo();
                }
            }
        });
        $(document).keydown(function( event ) {
            //console.log( event.type + ": " +  event.which );
            //console.log(event.ctrlKey);
            var el = self.getSelected();
            self.freeTransformUnplug();
            self.pathToolsUnplug();

            var step = event.ctrlKey ? 1 : 5;
            if (event.which == 46) {// delete
                svgCanvas.removeSelected();
            } else if (event.which == 38) {// up
                if (el) {
                    (el.type == 'set' ? el : [el]).map(function(e){
                        e.appendTransform([ 'T', 0, -step]);
                    });
                }
            } else if (event.which == 40) {// down
                if (el) {
                    (el.type == 'set' ? el : [el]).map(function(e){
                        e.appendTransform([ 'T', 0, step]);
                    });
                }
            } else if (event.which == 37) {// left
                if (el) {
                    (el.type == 'set' ? el : [el]).map(function(e){
                        e.appendTransform([ 'T', -step, 0]);
                    });
                }
            } else if (event.which == 39) {// right
                if (el) {
                    (el.type == 'set' ? el : [el]).map(function(e){
                        e.appendTransform([ 'T', step, 0]);
                    });
                }
            }
        });

        // The default pen.
        var _pen = null;

        var _layers = {'default' : _paper.set()};// 图层
        var _currentLayerName = 'default';// 当前图层名称


        // Public Methods
        //-----------------

        self.paper = function() {
            return _paper;
        };

        self.canvas = function() {
            return _canvas;
        };

        self.container = function() {
            return _container;
        };

        var _zoom = 1;
        self.setZoom = function(zoom) {

            var canvasCurrentWidth = _options.width / zoom;
            var canvasCurrentHeight = _options.height / zoom;
            var offsetX = (_paper.width - canvasCurrentWidth) / 2;
            var offsetY = (_paper.height - canvasCurrentHeight) / 2;
            _zoom = zoom;
            _paper.setViewBox(offsetX, offsetY, canvasCurrentWidth, canvasCurrentHeight, true)
        };
        self.getZoom = function() {
            return _zoom;
        };
        self.getZoomPosX = function(x) {
            x -= _container.offset().left;
            if (_paper._viewBox) {
                x /= _zoom;
                x += _paper._viewBox[0];
            }
            return x;
        };
        self.getZoomPosY = function(y) {
            y -= _container.offset().top;
            if (_paper._viewBox) {
                y /= _zoom;
                y += _paper._viewBox[1];
            }
            return y;
        };


        self.pen = function(value) {
            if (value === undefined) {
                return _pen;
            }
            _pen = value;
            return self; // function-chaining
        };

        self.isText = function(el) {
            return el ? el.attr('text') != undefined : false;
        };

        var backgroundImage = null;
        self.setBackgroundImage = function(src) {
            if (src == null || src == undefined) {
                if (backgroundImage != null) {
                    backgroundImage.remove();
                    backgroundImage = null;
                }
            } else {
                if (backgroundImage == null) {
                    backgroundImage = _paper.image(src, 0, 0, _paper.width, _paper.height);
                    backgroundImage.data("bg", "true");
                    backgroundImage.toBack();
                } else {
                    backgroundImage.attr("src", src);
                }
            }
        };

        self.createImage = function(src, x, y, width, height) {
            var imageEl = _paper.image(src, x, y, width, height).data("layerName", _currentLayerName);
            newElementAdded(imageEl);
            return imageEl;
        };

        self.createText = function(x, y, text) {
            return _paper.text(x, y, text).attr(_defaultAttr).attr('stroke', 'none').data("layerName", _currentLayerName);
        };


        /**
         * 当绘图工具改变时触发的回调函数
         * @param callback
         */
        self.toolChanged = function(callback) {
            self._toolChangeCallback = callback;
        };

        self.changeTool = function(type) {
            // 隐藏自由变形
            self.freeTransformUnplug();
            self.pathToolsUnplug();
            if (type == 'select') {
                _pen = new SelectTool(self);
                self.editing(type);
            } else if (type == 'zoom_area') {
                _pen = new ZoomAreaTool(self);
                self.editing(type);
            } else if (type == 'text_edit') {
                _pen = null;
                self.editing('text_edit');
            } else if (type == 'text') {
                _pen = new TextTool(self);
                self.editing(true);
            } else if (type == 'rect') {
                _pen = new RectTool(self);
                self.editing(true);
            } else if (type == 'circle') {
                _pen = new CircleTool(self);
                self.editing(true);
            } else if (type == 'ellipse') {
                _pen = new EllipseTool(self);
                self.editing(true);
            } else if (type == 'polygon') {
                _pen = new PolygonPen(self);
                self.editing(true);
            } else if (type == 'line') {
                _pen = new LineTool(self);
                self.editing(true);
            } else if (type == 'pen') {
                _pen = new PenTool(self);
                self.editing(true);
            } else if (type == 'hand') {// 鼠标移动画布
                _pen = null;//new HandTool(self);
                self.editing(false);
            }
            if (self._toolChangeCallback) {
                self._toolChangeCallback(type);
            }
            return self; // function-chaining
        };

        self.attrChanged = function(attr) {
            jQuery.extend(_defaultAttr, attr);
            if (self.selectedElement != null) {
                self.selectedElement.attr(attr);
            }
            return _defaultAttr;
        }


        var elementCreatedCallback = null;
        /**
         * 设置元素创建后的回调函数
         * @param callback
         */
        self.elementCreated = function(callback) {
            elementCreatedCallback = callback;
        }
        var _fireElementCreated = function (element) {
            _layers[_currentLayerName].push(element);
            element.data('layerName',  _currentLayerName);

            if (typeof elementCreatedCallback == "function") {
                elementCreatedCallback(element);
            }
        }

        self.removeElement = function(element) {
            if (element) {
                if (element.freeTransform) {
                    element.freeTransform.unplug();
                }
                element.remove();
            }
        }

        /**
         *
         * @returns {*}
         */
        self.getCurrentLayer = function() {
            return _layers[_currentLayerName];
        };

        self.getCurrentLayerName = function() {
            return _currentLayerName;
        };

        var elementDropedCallback = null;
        /**
         * dom节点拖拽后在在svg节点上放下的回调
         * @param callback
         */
        self.elementDroped = function(callback) {
            elementDropedCallback = callback;
        };

        /**
         * 获取当前选中的元素
         * @returns {*}
         */
        self.getSelected = function() {
            return self.selectedElement;
        };

        var elementSelectedCallback = null;
        self.selectChanged = function(callback) {
            elementSelectedCallback = callback;
        }
        self.fireElementSelected = function (elements) {
            var element = elements;
            if (self.selectedElement != element) {
                self.selectedElement = element;
                if (typeof elementSelectedCallback == "function") {
                    elementSelectedCallback(element);
                }
            }
        }

        self.removeSelected = function() {
            self.removeElement(self.selectedElement);
        }

        self.cloneSelected = function() {
            if (self.selectedElement) {
                var el = self.selectedElement.clone();
                el.appendTransform(['T10,10']);
                newElementAdded(el);
            }
        }

        self.selectedToBack = function() {
            if (self.selectedElement != null) {
                self.selectedElement.toBack();
                if (backgroundImage != null) {
                    backgroundImage.toBack();
                }
            }
        }

        self.selectedToFront = function() {
            if (self.selectedElement != null) {
                self.selectedElement.toFront();
            }
        };

        self.pathToolsUnplug = function() {
            if (self.selectedElement != null) {
                if (self.selectedElement.type == 'path' && self.selectedElement.pathTools) {
                    self.selectedElement.pathTools.unplug();
                }
                self.selectedElement.attr('cursor','');
            }
            _paper.forEach(function (el) {
                if (el.freeTransform) {
                    el.freeTransform.unplug();
                    //_paper.freeTransform(el).unplug();
                }
                el.attr('cursor','');
            });
        };

        /**
         * 隐藏变形工具
         */
        self.freeTransformUnplug = function() {
            if (self.selectedElement != null) {
                if (self.selectedElement.freeTransform) {
                    self.selectedElement.freeTransform.unplug();
                }
                self.selectedElement.attr('cursor','');
            }
            _paper.forEach(function (el) {
                if (el.freeTransform) {
                    el.freeTransform.unplug();
                }
                el.attr('cursor','');
            });
        };

        self.toJson = function() {
            var elementsJson = self.paper().toJSON(function(el, data) {
                if (el.data("deleted")) {
                    return;
                }

                if (el.data("temp")) {// 临时工具节点不显示
                    return;
                }

                $.extend(data, el.data());

                //el.data('layerName');
                //data.layerName = el.data('layerName');
//                data.ft = {};
                if ( el.freeTransform != null ) {// 保存形状编辑器状态
//                    data.ft.attrs = el.freeTransform.attrs;
                    _paper.freeTransform(el).unplug();
                }

                return data;
            });
            var json = {width : _paper.width, height: _paper.height, elements: JSON.parse(elementsJson)};
            return JSON.stringify(json);
//            return self.paper().toJSON(function(el, data) {
//                $.extend(data, el.data());
//
//                //el.data('layerName');
//                //data.layerName = el.data('layerName');
////                data.ft = {};
//                if ( el.freeTransform != null ) {// 保存形状编辑器状态
////                    data.ft.attrs = el.freeTransform.attrs;
//                    _paper.freeTransform(el).unplug();
//                }
//
//                return data;
//            });
        }

        self.fromJson  = function (json) {
            if (!json || json == "") {
                return;
            }

            var json = JSON.parse(json);
            svgCanvas.reset();
            self.setCanvasSize(json.width, json.height);
            self.paper().fromJSON(json.elements, function(el, data) {
                // Recreate the set using the identifier
                if ( !_layers[data.layerName] ) _layers[data.layerName] = _paper.set();

                // Place each element back into the set
                _layers[data.layerName].push(el);

                //el.data('layerName', data.layerName);
                for ( var k in data ) {
                    el.data(k, data[k]);
                }

                if (el.type == 'image' && data.bg) {
                    backgroundImage = el;
                }

                initDragDrop(el);
                return el;
            });
        }

        self.alignLeft = function(elSet) {
            //var selEl = svgCanvas.getSelected();
            if (elSet != null && elSet.type == 'set') {
                var bbox = elSet.getBBox();

                elSet.forEach(function (el) {
                    var dx = bbox.x - el.getBBox().x;
                    el.appendTransform([ 'T', dx, 0]);
                });
                _paper.freeTransform(elSet, {draw:'bbox',
                    keepRatio:[ 'axisX', 'axisY', 'bboxCorners']});
            }
        }

        self.alignRight = function(elSet ) {
            if (elSet != null && elSet.type == 'set') {
                var bbox = elSet.getBBox();

                elSet.forEach(function (el) {
                    var dx = bbox.x2 - el.getBBox().x2;
                    el.appendTransform([ 'T', dx, 0]);
                });
                _paper.freeTransform(elSet, {draw:'bbox',
                    keepRatio:[ 'axisX', 'axisY', 'bboxCorners']});
            }
        }

        self.alignCenter = function (elSet ) {
            if (elSet != null && elSet.type == 'set') {
                var bbox = elSet.getBBox();
                elSet.forEach(function (el) {
                    if (el.freeTransform) {
                        _paper.freeTransform(el).unplug();
                    }

                    var elbbox = el.getBBox();
                    var dx = (bbox.x + bbox.width / 2) - (elbbox.x + elbbox.width / 2)
                    el.appendTransform([ 'T', dx, 0]);

                });
                _paper.freeTransform(elSet, {draw:'bbox',
                    keepRatio:[ 'axisX', 'axisY', 'bboxCorners']});
            }
        }

        self.alignMiddle = function (elSet ) {
            if (elSet != null && elSet.type == 'set') {
                var bbox = elSet.getBBox();

                if (elSet.freeTransform) {
                    _paper.freeTransform(elSet).unplug();
                }
                elSet.forEach(function (el) {
                    var elbbox = el.getBBox();
                    var dy = (bbox.y + bbox.height / 2) - (elbbox.y + elbbox.height / 2)
                    el.appendTransform([ 'T', 0, dy]);
                });
                _paper.freeTransform(elSet, {draw:'bbox',
                    keepRatio:[ 'axisX', 'axisY', 'bboxCorners']});
            }
        }

        self.alignTop = function(elSet) {
            //var selEl = svgCanvas.getSelected();
            if (elSet != null && elSet.type == 'set') {
                var bbox = elSet.getBBox();

                elSet.forEach(function (el) {
                    var elbbox = el.getBBox();
                    var dy = bbox.y - elbbox.y;
                    el.appendTransform([ 'T', 0, dy]);
                });
                _paper.freeTransform(elSet, {draw:'bbox',
                    keepRatio:[ 'axisX', 'axisY', 'bboxCorners']});
            }
        }

        self.alignBottom = function(elSet ) {
            if (elSet != null && elSet.type == 'set') {
                var bbox = elSet.getBBox();

                elSet.forEach(function (el) {
                    var dy = bbox.y2 - el.getBBox().y2;
                    el.appendTransform([ 'T', 0, dy]);
                });
                _paper.freeTransform(elSet, {draw:'bbox',
                    keepRatio:[ 'axisX', 'axisY', 'bboxCorners']});
            }
        }

        self.initFreeTransform  = function(element) {
            if (!element) {
                return;
            }
            if (element.freeTransform == null || element.freeTransform === undefined) {
                element.attr('cursor','move');

                var oldTransform = '';
                if (element.type == 'set') {
                    oldTransform = [];
                    element.forEach(function(el){
                        oldTransform.push(el.transform().toString());
                    });
                } else {
                    oldTransform = element.transform.toString();
                }

                self.paper().freeTransform(element, {draw:'bbox',
                        keepRatio:[ 'axisX', 'axisY', 'bboxCorners']},
                    function(ft, events) {
                        //console.log(events);
                        if ($.inArray('init', events) == -1) {// 用户使用变形工具后，自动修改当前编辑格式
                            if (_pen) {
                                _pen.abort(self);
                            }
                            if (_options.editing != 'select') {
                                _pen = new SelectTool(self);
                                self.editing('select');
                                if (self._toolChangeCallback) {
                                    self._toolChangeCallback('select');
                                }
                            }
                        }

                        if (events[0].indexOf("end") != -1) {
                            var cmd = {
                                undo: function () {
                                    self.freeTransformUnplug();
//                                    this.el.transform(this.oldTransform);

                                    console.log(this.oldTransform);
                                    if (this.el.type == 'set') {
                                        this.el.forEach(function(el){
                                            el.transform(this.oldTransform.pop());
                                        });
                                    } else {
                                        this.el.transform(this.oldTransform);
                                    }
//                                    self.initFreeTransform(this.el);
                                },
                                redo: function () {
//                                    this.el.transform(this.newTransform);
                                    self.freeTransformUnplug();
                                    // FIXME: freeTransform bug，撤销后自由变形工具显示位置发生偏移

                                    if (this.el.type == 'set') {
                                        this.el.forEach(function(el){
                                            if (this.newTransform) {
                                                el.transform(this.newTransform.pop());
                                            }
                                        });
                                    } else {
                                        this.el.transform(this.newTransform);
                                    }
//                                    self.initFreeTransform(this.el);
                                }
                            };
                            cmd.oldTransform = oldTransform;
                            cmd.newTransform = '';
                            if (element.type == 'set') {
                                cmd.newTransform = [];
                                element.forEach(function(el){
                                    cmd.newTransform.push(el.transform.toString());
                                });
                            } else {
                                cmd.newTransform = element.transform.toString();
                            }

                            cmd.el = element;
                            oldTransform = cmd.newTransform;
                            undoManager.add(cmd);
                        }

                    }
                );// freeTransform init
            }
        }


        self.undoable = function() {
            return undoManager.hasUndo();
        };

        self.undo = function() {
            undoManager.undo();
            return self; // function-chaining
        };

        self.redoable = function() {
            return undoManager.hasRedo();
        };

        self.redo = function() {
            undoManager.redo();
            return self; // function-chaining
        };

        self.addHistory = function(cmd) {
            undoManager.add(cmd);
        };

        var initDragDrop = function(newElement) {
            newElement.node.ondragenter = function(event){
                if (!newElement.oldOpacity) {
                    newElement.oldOpacity = newElement.attr('opacity');
                }
                newElement.animate({opacity: newElement.oldOpacity * .5}, 500, ">");
            };
            newElement.node.ondragover = function(event){
                event.preventDefault();
            };
            newElement.node.ondrop = function(event){
                event.preventDefault();
                if (newElement.oldOpacity) {
                    newElement.animate({opacity: newElement.oldOpacity}, 500, ">");
                }
                if (typeof(elementDropedCallback) == 'function') {
                    elementDropedCallback(event, newElement);
                }
            };
            newElement.node.ondragleave = function(event){
                event.preventDefault();
                if (newElement.oldOpacity) {
//                                newElement.attr({'opacity': newElement.oldOpacity})
                    newElement.animate({opacity: newElement.oldOpacity}, 500, ">");
                }
            };
        };

        var newElementAdded = function(newElement ) {
            initDragDrop(newElement);

            self.freeTransformUnplug();

            //.hideHandles();
            if (newElement.attr("text") != undefined) {// 文本元素
                newElement.click(function(){
                    if (_options.editing == "text_edit") {
                        // Retrieve created <input type=text> field
                        var input = this.inlineTextEditing.startEditing();
                        input.addEventListener("blur", function(e){
                            newElement.inlineTextEditing.stopEditing();
                        }, false);
                        self.fireElementSelected(this);
                    }
                });

                _paper.inlineTextEditing(newElement);
                var input = null;

                if (newElement.attr("text") == "") {
                    newElement.attr({"text": "请输入文本"});
                    input = newElement.inlineTextEditing.startEditing();
                    input.value = "";
                    input.setAttribute("placeholder", "请输入文本");
                } else {
                    input = newElement.inlineTextEditing.startEditing();
                }
                input.addEventListener("blur", function(e){
                    newElement.inlineTextEditing.stopEditing();
                    if (input.value == "") {// 未输入文本自动删除该元素
                        self.removeElement(newElement);
                    }
                }, false);
            }
            if (newElement.type != 'path') {// 路径绘制完后不显示自由变形工具
                self.initFreeTransform(newElement);
            } else {

                newElement.dblclick(function(){
                    self.freeTransformUnplug();
                    this.pathTools.plug();
                });
            }
            _fireElementCreated(newElement);
            self.fireElementSelected(newElement);
        };

        var handTool = new function() {

            var startX = null;
            var startY = null;
            var scrollLeft = null;
            var scrollTop = null;

            this.onFinish = function(){

            };

            this.mousedown = function(e) {
                self.freeTransformUnplug();
                self.fireElementSelected(null);
                var $container = $(_container);
                var $areaCanvas = $container.parent().parent();
                $container.css("cursor", "grabbing");
                $container.css("cursor", "-webkit-grabbing");
                $container.css("cursor", "-moz-grabbing");
                startX = e.pageX;
                startY = e.pageY;
                scrollLeft = $areaCanvas.scrollLeft();
                scrollTop = $areaCanvas.scrollTop();
            };

            this.mouseup = function(e) {
                $(_container).css("cursor", "");
                startX = null;
                startY = null;
            };

            this.mousemove = function(e) {
                if (startX != null && startY != null) {
                    var $container = $(_container);
                    var $areaCanvas = $container.parent().parent();
                    var x = scrollLeft + startX - e.pageX;
                    var y = scrollTop + startY - e.pageY;
                    $areaCanvas.scrollLeft(x);
                    $areaCanvas.scrollTop(y);
                }
            };
        };
        self.editing = function(mode) {
            if (mode === undefined) {
                return _options.editing;
            }

            _options.editing = mode;
            if (_options.editing) {
                $(_container).unbind("mousedown", handTool.mousedown);
                $(document).unbind("mousemove", handTool.mousemove);
                $(document).unbind("mouseup", handTool.mouseup);

                if (_options.editing == "erase") {
                    // Cursor is crosshair, so it looks like we can do something.
                    $(_container).css("cursor", "crosshair");
                    $(_container).unbind("mousedown", _mousedown);
                    $(_container).unbind("mousemove", _mousemove);
                    $(_container).unbind("mouseup", _mouseup);
                    $(document).unbind("mouseup", _mouseup);
                    $(_container).unbind("dblclick", _dblclick);

                    // iPhone Events
                    var agent = navigator.userAgent;
                    if (agent.indexOf("iPhone") > 0 || agent.indexOf("iPod") > 0) {
                        $(_container).unbind("touchstart", _touchstart);
                        $(_container).unbind("touchmove", _touchmove);
                        $(_container).unbind("touchend", _touchend);
                    }
                } else if (_options.editing == "text_edit") {
                    // Reverse the settings above.
                    $(_container).css("cursor", "default");
                    $(_container).unbind("mousedown", _mousedown);
                    $(_container).unbind("mousemove", _mousemove);
                    $(_container).unbind("mouseup", _mouseup);
                    $(document).unbind("mouseup", _mouseup);
                    $(_container).unbind("dblclick", _dblclick);

                    // iPhone Events
                    var agent = navigator.userAgent;
                    if (agent.indexOf("iPhone") > 0 || agent.indexOf("iPod") > 0) {
                        $(_container).unbind("touchstart", _touchstart);
                        $(_container).unbind("touchmove", _touchmove);
                        $(_container).unbind("touchend", _touchend);
                    }
                } else {
                    if (_options.editing == "select") {
                        $(_container).css("cursor", "default");
                    } else {
                        // Cursor is crosshair, so it looks like we can do something.
                        $(_container).css("cursor", "crosshair");
                    }

                    $(_container).mousedown(_mousedown);
//                    $(_container).mousemove(_mousemove);
//                    $(_container).mouseup(_mouseup);
                    $(_container).dblclick(_dblclick);

                    // Handle the case when the mouse is released outside the canvas.
                    $(document).mouseup(_mouseup);
                    $(document).mousemove(_mousemove);

                    // iPhone Events
                    var agent = navigator.userAgent;
                    if (agent.indexOf("iPhone") > 0 || agent.indexOf("iPod") > 0) {
                        $(_container).bind("touchstart", _touchstart);
                        $(_container).bind("touchmove", _touchmove);
                        $(_container).bind("touchend", _touchend);
                    }
                }
            } else {// 鼠标移动画面
                // Reverse the settings above.
                $(_container).css("cursor", '');
//                $(_container).css("cursor", "-webkit-grabbing");
                $(_container).unbind("mousedown", _mousedown);
                $(_container).unbind("mousemove", _mousemove);
                $(_container).unbind("mouseup", _mouseup);
                $(document).unbind("mouseup", _mouseup);
                $(_container).unbind("dblclick", _dblclick);

                // iPhone Events
                var agent = navigator.userAgent;
                if (agent.indexOf("iPhone") > 0 || agent.indexOf("iPod") > 0) {
                    $(_container).unbind("touchstart", _touchstart);
                    $(_container).unbind("touchmove", _touchmove);
                    $(_container).unbind("touchend", _touchend);
                }

                $(_container).mousedown(handTool.mousedown);
                $(document).mouseup(handTool.mouseup);
                $(document).mousemove(handTool.mousemove);
/*                var startX = null;
                var startY = null;
                var scrollLeft = null;
                var scrollTop = null;
                $(_container).mousedown(function(e){// 点击空白位置时，隐藏当前变形工具
                    if (!e.isDefaultPrevented()) {
                        self.freeTransformUnplug();
                        self.fireElementSelected(null);
                    }
                    $(_container).css("cursor", "move");
                    startX = e.pageX;
                    startY = e.pageY;

                    var $areaCanvas = _container.parent();
                    scrollLeft = $areaCanvas.parent().scrollLeft();
                    scrollTop = $areaCanvas.parent().scrollTop();
                });
                $(_container).mouseup(function(e){// 点击空白位置时，隐藏当前变形工具
                    $(_container).css("cursor", "default");
                    startX = null;
                    startY = null;
                });
                $(_container).mousemove(function(e){// 点击空白位置时，隐藏当前变形工具
                    if (startX != null && startY != null) {
                        var $areaCanvas = _container.parent();
                        var x = scrollLeft + startX - e.pageX;
                        var y = scrollTop + startY - e.pageY;
                        $areaCanvas.parent().scrollLeft(x);
                        $areaCanvas.parent().scrollTop(y);
                    }
                });*/
            }

            if (_pen != null) {
                _pen.onFinish(function(newElement ) {
                    if (newElement) {
                        var cmd = {
                            undo: function () {
                                //this.el.remove()
                                this.el.hide()
                                this.el.data("deleted", true);
                                var layerName = this.el.data('layerName');
                                if (layerName && _layers[layerName]) {
                                    _layers[layerName].exclude(this.el);
                                }
                                self.freeTransformUnplug();
                                self.pathToolsUnplug();
                            },
                            redo: function () {
                                this.el.show()
                                this.el.removeData("deleted");
                                var layerName = this.el.data('layerName');
                                if (layerName && _layers[layerName]) {
                                    _layers[layerName].push(this.el);
                                }
                            }
                        };
                        cmd.el = newElement;
                        //cmd.redoJson = [$.extend({type: newElement.type}, newElement.attr())];
                        //console.log(cmd.redoJson);
                        undoManager.add(cmd);
                        newElementAdded(newElement);
                    }
                });
            }

            return self; // function-chaining
        }

        // Change events
        //----------------

        var _change_fn = function() {};
        self.change = function(fn) {
            if (fn == null || fn === undefined) {
                _change_fn = function() {};
            } else if (typeof fn == "function") {
                _change_fn = fn;
            }
        };

        function _fire_change() {
            _change_fn();
        };

        // Miscellaneous methods
        //------------------

        function _disable_user_select() {
            if (jQuery.browser.msie) {
                $("body").attr("onselectstart", "return false;");
            }
        }

        function _enable_user_select() {
            $("*").css("-webkit-user-select", "text");
            $("*").css("-moz-user-select", "text");
            if (jQuery.browser.msie) {
                $("body").removeAttr("onselectstart");
            }
        }

        // Event handlers
        //-----------------
        // We can only attach events to the container, so do it.

        function _pathclick(e) {
            if (_options.editing == "erase") {
                var stroke = this.attr();
                stroke.type = this.type;

                _action_history.add({
                    type: "erase",
                    stroke: stroke
                });

                for (var i = 0, n = _strokes.length; i < n; i++) {
                    var s = _strokes[i];
                    if (equiv(s, stroke)) {
                        _strokes.splice(i, 1);
                    }
                }

                _fire_change();

                this.remove();
            }
        };

        function _mousedown(e) {
            _disable_user_select();
            _pen.mousedown(e, self);
        };

        function _mousemove(e) {
            if (_pen) {
                _pen.mousemove(e, self);
            }
        };

        function _mouseup(e) {
            _pen.mouseup(e, self);
        };

        function _dblclick(e) {
            if (typeof _pen.dblclick == "function") {
                _pen.dblclick(e, self);
            }
        }

        function _touchstart(e) {
            e = e.originalEvent;
            e.preventDefault();

            if (e.touches.length == 1) {
                var touch = e.touches[0];
                _mousedown(touch);
            }
        }

        function _touchmove(e) {
            e = e.originalEvent;
            e.preventDefault();

            if (e.touches.length == 1) {
                var touch = e.touches[0];
                _mousemove(touch);
            }
        }

        function _touchend(e) {
            e = e.originalEvent;
            e.preventDefault();

            _mouseup(e);
        }

        // Setup
        //--------

        self.editing(_options.editing);
    };


    /**
     * The default Pen object.
     */
    var PenTool = function() {
        var self = this;

        // Drawing state
        var _drawing = false;
        var _c = null;
        var _points = [];

        self.abort = function(canvas) {
            if (_c != null) {
                canvas.removeElement(_c);
            }
            _drawing = false;
            _c = null;
        };

        self.mousedown = function(e, canvas) {
            _drawing = true;

            var x = e.pageX - _offset.left,
                y = e.pageY - _offset.top;
            _points.push([x, y]);

            _c = canvas.paper().path();

            _c.attr({ "stroke-linecap": "round", "stroke-linejoin": "round" });
            _c.attr(canvas.attrChanged());
        };

        self.mouseup = function(e, sketchpad) {
            var path = null;

            if (_c != null) {
                if (_points.length <= 1) {
                    _c.remove();
                } else {
                    path = _c;
                }
            }

            _drawing = false;
            _c = null;
            _points = [];

            return path;
        };

        self.mousemove = function(e, sketchpad) {
            if (_drawing == true) {
                var x = e.pageX - _offset.left,
                    y = e.pageY - _offset.top;
                _points.push([x, y]);
                _c.attr({ path: points_to_svg() });
            }
        };

        function points_to_svg() {
            if (_points != null && _points.length > 1) {
                var p = _points[0];
                var path = "M" + p[0] + "," + p[1];
                for (var i = 1, n = _points.length; i < n; i++) {
                    p = _points[i];
                    path += "L" + p[0] + "," + p[1];
                }
                return path;
            } else {
                return "";
            }
        };
    };

    /**
     * Utility to generate string representation of an object.
     */
    function inspect(obj) {
        var str = "";
        for (var i in obj) {
            str += i + "=" + obj[i] + "\n";
        }
        return str;
    }

    var SelectTool = function(canvas) {
        var self = this;
        self.canvas = canvas;
        self.paper = canvas.paper();

        var _offset = null;
        var _drawing = false;
        var _rect = null;
        var x, y;

        self.abort = function(canvas) {
            if (_rect != null) {
                _rect.remove();
            }
            _rect = null;
        };

        var _finishCallBack = null;
        self.onFinish = function(finishCallBack ) {
            _finishCallBack = finishCallBack;
            if (typeof _finishCallBack != 'function') {
                _finishCallBack = function(){};
            }
        };

        self.mousedown = function(e) {
            x = self.canvas.getZoomPosX(e.pageX);
            y = self.canvas.getZoomPosY(e.pageY);

            if (_rect == null) {
                _rect = self.paper.rect(x, y, 0, 0);
                _rect.attr({'stroke-dasharray':'--', 'stroke-width': 1, 'stroke': 'blue', 'stroke-opacity':0.8});
//                e.stopPropagation();
            }
        };

        self.mouseup = function(e) {
            if (_rect != null) {
                _rect.remove();
            }

            if (_rect != null) {
                var x1 = self.canvas.getZoomPosX(e.pageX);
                var y1 = self.canvas.getZoomPosY(e.pageY);

                console.log("X:", x, "Y:", y);
                console.log("X1:", x1, "Y1:", y1);
                if (x1 == x && y1 == y) {// 点选择
                    canvas.freeTransformUnplug();
                    canvas.pathToolsUnplug();

                    var el = self.paper.top;
                    while(el) {
                        if (el.data('layerName') == self.canvas.getCurrentLayerName()) {
                            var bbox = el.getBBox();
                            if (bbox && el.data('bg') != 'true') {
                                var minX1 = x1 > x ? x : x1;
                                var minY1 = y1 > y ? y : y1;
                                var maxX1 = x1 > x ? x1 : x;
                                var maxY1 = y1 > y ? y1 : y;

                                var minx   =   Math.max(minX1,   bbox.x)
                                var miny   =   Math.max(minY1,   bbox.y)
                                var maxx   =   Math.min(maxX1,   bbox.x2)
                                var maxy   =   Math.min(maxY1,   bbox.y2)
                                if (!(minx > maxx || miny > maxy)) {
                                    if (el && el.data('bg') != 'true') {
                                        self.canvas.initFreeTransform(el);
                                        self.canvas.fireElementSelected(el);
                                    } else {
                                        self.canvas.fireElementSelected(null);
                                    }
                                    break;
                                }
                            }
                        }
                        el = el.prev;
                    }

//                    var el = self.paper.getElementByPoint(e.clientX, e.clientY);
//                    console.log(el);
//                    if (el && el.data('bg') != 'true') {
//                        self.canvas.initFreeTransform(el);
//                        self.canvas.fireElementSelected(el);
//                    } else {
//                        self.canvas.fireElementSelected(null);
//                    }
                } else {// 面选择
                    var elements = self.canvas.paper().set();
                    canvas.freeTransformUnplug();
                    canvas.pathToolsUnplug();

                    self.canvas.getCurrentLayer().forEach(function (el) {
                        var bbox = el.getBBox();
                        if (bbox && el.data('bg') != 'true') {
                            var minX1 = x1 > x ? x : x1;
                            var minY1 = y1 > y ? y : y1;
                            var maxX1 = x1 > x ? x1 : x;
                            var maxY1 = y1 > y ? y1 : y;

                            var minx   =   Math.max(minX1,   bbox.x)
                            var miny   =   Math.max(minY1,   bbox.y)
                            var maxx   =   Math.min(maxX1,   bbox.x2)
                            var maxy   =   Math.min(maxY1,   bbox.y2)
                            if (!(minx > maxx || miny > maxy)) {
                                elements.push(el);
                            }
                        }
                    });
                    if (elements.length > 0) {
                        if (elements.length == 1) {
                            var el = elements.pop();
                            self.canvas.initFreeTransform(el);
                            self.canvas.fireElementSelected(el);
                            delete elements;
                        } else {
                            self.canvas.initFreeTransform(elements);
                            self.canvas.fireElementSelected(elements);
                        }
                    } else {
                        self.canvas.fireElementSelected(null);
                    }
                }
                //e.stopPropagation();
            }

            _rect = null;
        };

        self.mousemove = function(e) {
            if (_rect != null) {
//                e.stopPropagation();
                var x2 = self.canvas.getZoomPosX(e.pageX);
                var y2 = self.canvas.getZoomPosY(e.pageY);

                if (x2 > x) {
                   if (y2 > y) {
                       _rect.attr({x : x, y : y, width: x2 - x, height: y2 - y});
                   } else {
                       _rect.attr({x : x, y : y2, width: x2 - x, height: y - y2});
                   }
                } else {
                    if (y2 > y) {
                        _rect.attr({x : x2, y : y, width: x - x2, height: y2 - y});
                    } else {
                        _rect.attr({x : x2, y : y2, width: x - x2, height: y - y2});
                    }
                }
            }
        };
    };

    var ZoomAreaTool = function(canvas) {
        var self = this;
        self.canvas = canvas;
        self.paper = canvas.paper();

        var _drawing = false;
        var _rect = null;
        var x, y, x1, y1;

        self.abort = function(canvas) {
        };

        var _finishCallBack = null;
        self.onFinish = function(finishCallBack ) {
            _finishCallBack = finishCallBack;
            if (typeof _finishCallBack != 'function') {
                _finishCallBack = function(){};
            }
        };

        self.mousedown = function(e) {
            x = self.canvas.getZoomPosX(e.pageX);
            y = self.canvas.getZoomPosY(e.pageY);

            if (_rect == null) {
                _rect = self.paper.rect(x, y, 0, 0).attr({'stroke-dasharray':'--', 'stroke-width': 1, 'stroke': 'blue', 'stroke-opacity':0.8});
                e.stopPropagation();
            }
        };

        self.mouseup = function(e) {
            if (_rect != null) {
                e.stopPropagation();
                var x1 = self.canvas.getZoomPosX(e.pageX);
                var y1 = self.canvas.getZoomPosY(e.pageY);

                _rect.remove();
                if (x1 == x && y1 == y) {// 点选择
                    self.canvas.setZoom(self.canvas.getZoom() * 1.1);
                } else {// 面选择
                    self.canvas.setZoom(self.canvas.getZoom() * 1.1);
                }
            }

            _rect = null;
        };

        self.mousemove = function(e) {
            if (_rect != null) {
                e.stopPropagation();
                var x2 = self.canvas.getZoomPosX(e.pageX);
                var y2 = self.canvas.getZoomPosY(e.pageY);

                if (x2 > x) {
                    if (y2 > y) {
                        _rect.attr({x : x, y : y, width: x2 - x, height: y2 - y});
                    } else {
                        _rect.attr({x : x, y : y2, width: x2 - x, height: y - y2});
                    }
                } else {
                    if (y2 > y) {
                        _rect.attr({x : x2, y : y, width: x - x2, height: y2 - y});
                    } else {
                        _rect.attr({x : x2, y : y2, width: x - x2, height: y - y2});
                    }
                }
            }
        };
    };

    var RectTool = function(canvas) {
        var self = this;
        self.canvas = canvas;
        self.paper = canvas.paper();

        // Drawing state
        var _drawing = false;
        var _rect = null;
        var _width = 5;
        var x, y;

        self.abort = function() {
            if (_rect != null) {
                self.canvas.removeElement(_rect);
            }
            _drawing = false;
            _rect = null;
        };

        var _finishCallBack = null;
        self.onFinish = function(finishCallBack ) {
            _finishCallBack = finishCallBack;
            if (typeof _finishCallBack != 'function') {
                _finishCallBack = function(){};
            }
        };

        self.mousedown = function(e) {
            _drawing = true;

            if (_rect == null) {
                e.stopPropagation();
                if (self.canvas["stroke-width"]) {
                    _width = self.canvas["stroke-width"];
                }

                x = self.canvas.getZoomPosX(e.pageX);
                y = self.canvas.getZoomPosY(e.pageY);

                _rect = self.paper.rect(x, y, 0, 0);

                _rect.attr(self.canvas.attrChanged());
            }
        };

        self.mouseup = function(e) {

            if (_rect != null) {
                e.stopPropagation();
                var x2 = self.canvas.getZoomPosX(e.pageX);
                var y2 = self.canvas.getZoomPosY(e.pageY);
                if (Math.abs(x2 - x) > _width && Math.abs(y2 - y) > _width) {
                    _finishCallBack(_rect);
                } else {
                    _rect.remove();
                }
            }

            _drawing = false;
            _rect = null;

        };

        self.mousemove = function(e) {
            if (_rect!=null && _drawing == true) {
                e.stopPropagation();
                var x2 = self.canvas.getZoomPosX(e.pageX);
                var y2 = self.canvas.getZoomPosY(e.pageY);

                if (x2 > x) {
                    if (y2 > y) {
                        _rect.attr({x : x, y : y, width: x2 - x, height: y2 - y});
                    } else {
                        _rect.attr({x : x, y : y2, width: x2 - x, height: y - y2});
                    }
                } else {
                    if (y2 > y) {
                        _rect.attr({x : x2, y : y, width: x - x2, height: y2 - y});
                    } else {
                        _rect.attr({x : x2, y : y2, width: x - x2, height: y - y2});
                    }
                }
            }
        };
    };

    var CircleTool = function(canvas) {
        var self = this;
        self.canvas = canvas;
        self.paper = canvas.paper();

        // Drawing state
        var _drawing = false;
        var _c = null;
        var _width = 5;
        var x, y;

        self.abort = function() {
            if (_c != null) {
                self.canvas.removeElement(_c);
            }
            _drawing = false;
            _c = null;
        };

        var _finishCallBack = null;
        self.onFinish = function(finishCallBack ) {
            _finishCallBack = finishCallBack;
            if (typeof _finishCallBack != 'function') {
                _finishCallBack = function(){};
            }
        };

        self.mousedown = function(e) {
            _drawing = true;

            if (_c == null) {
                e.stopPropagation();
                if (self.canvas["stroke-width"]) {
                    _width = self.canvas["stroke-width"];
                }

                x = self.canvas.getZoomPosX(e.pageX);
                y = self.canvas.getZoomPosY(e.pageY);

                _c = self.canvas.paper().circle(x, y, 0);

                _c.attr(self.canvas.attrChanged());
            }
        };

        self.mouseup = function(e) {

            if (_c != null) {
                e.stopPropagation();
                var x2 = self.canvas.getZoomPosX(e.pageX);
                var y2 = self.canvas.getZoomPosY(e.pageY);
                var offsetX = x2 - x;
                var offsetY = y2 - y;
                if (Math.abs(offsetX) > _width && Math.abs(offsetY) > _width) {
                    _finishCallBack(_c);
                } else {
                    _c.remove();
                }
            }

            _drawing = false;
            _c = null;

        };

        self.mousemove = function(e) {
            if (_drawing == true) {
                e.stopPropagation();
                var x2 = self.canvas.getZoomPosX(e.pageX);
                var y2 = self.canvas.getZoomPosY(e.pageY);
                var offsetX = x2 - x;
                var offsetY = y2 - y;
                var r = Math.max(Math.abs(offsetX), Math.abs(offsetY));
                _c.attr({r: r});
            }
        };
    };

    var EllipseTool = function(canvas) {
        var self = this;
        self.canvas = canvas;
        self.paper = canvas.paper();

        // Drawing state
        var _drawing = false;
        var _ellipse = null;
        var _width = 5;
        var _originX;
        var _originY;
        var x, y;

        self.abort = function() {
            if (_ellipse != null) {
                self.canvas.removeElement(_ellipse);
            }
            _drawing = false;
            _ellipse = null;
        };

        var _finishCallBack = null;
        self.onFinish = function(finishCallBack ) {
            _finishCallBack = finishCallBack;
            if (typeof _finishCallBack != 'function') {
                _finishCallBack = function(){};
            }
        };

        self.mousedown = function(e) {
            _drawing = true;

            if (_ellipse == null) {
                e.stopPropagation();
                if (self.canvas["stroke-width"]) {
                    _width = self.canvas["stroke-width"];
                }

                x = self.canvas.getZoomPosX(e.pageX);
                y = self.canvas.getZoomPosY(e.pageY);

                _ellipse = self.canvas.paper().ellipse(x, y, 0, 0);

                _ellipse.attr(self.canvas.attrChanged());
            }
        };

        self.mouseup = function(e) {

            if (_ellipse != null) {
                e.stopPropagation();
                var x2 = self.canvas.getZoomPosX(e.pageX);
                var y2 = self.canvas.getZoomPosY(e.pageY);
                var offsetX = x2 - x;
                var offsetY = y2 - y;
                if (Math.abs(offsetX) > _width && Math.abs(offsetY) > _width) {
                    _finishCallBack(_ellipse);
                } else {
                    _ellipse.remove();
                }
            }

            _drawing = false;
            _ellipse = null;

        };

        self.mousemove = function(e) {
            if (_drawing == true) {
                var x2 = self.canvas.getZoomPosX(e.pageX);
                var y2 = self.canvas.getZoomPosY(e.pageY);
                var rx = x2 - x;
                var ry = y2 - y;
                if (rx > 0) {
                    if (ry > 0) {
                        _ellipse.attr({x:x, y: y, rx: rx, ry: ry});
                    } else {
                        _ellipse.attr({x:x, y: y + ry, rx: rx, ry: -ry});
                    }
                } else {
                    if (ry > 0) {
                        _ellipse.attr({x:x + rx, y: y, rx: -rx, ry: ry});
                    } else {
                        _ellipse.attr({x:x + rx, y: y + ry, rx: -rx, ry: -ry});
                    }
                }
            }
        };
    };

    var TextTool = function(canvas) {
        var self = this;
        self.canvas = canvas;
        self.paper = canvas.paper();

        // Drawing state
        var _text = null;

        self.abort = function() {
            if (_text != null) {
                self.canvas.removeElement(_text);
            }
            _text = null;
        };

        var _finishCallBack = null;
        self.onFinish = function(finishCallBack ) {
            _finishCallBack = finishCallBack;
            if (typeof _finishCallBack != 'function') {
                _finishCallBack = function(){};
            }
        };

        self.mousedown = function(e) {

            if (_text == null) {

                var x = self.canvas.getZoomPosX(e.pageX);
                var y = self.canvas.getZoomPosY(e.pageY);

                _text = self.canvas.paper().text(x, y, "");
                _text.attr(self.canvas.attrChanged()).attr({'stroke': 'none', 'text-anchor': 'start'});
            }
        };

        self.mouseup = function(e) {
            if (_text != null) {
                e.stopPropagation();
                _finishCallBack(_text);
            }
            _text = null;
        };

        self.mousemove = function(e) {
        };
    };

    var PolygonPen = function(canvas) {
        var self = this;
        self.canvas = canvas;
        self.paper = canvas.paper();

        // Drawing state
        var _drawing = false;
        var _c = null;
        var discattr = {fill: "#FFFFFF", stroke: "#CCCCCC", 'stroke-width':2};
        var path = [];
        var controls = [];
        var mousedown = false;
        var curveStart = true;

        self.abort = function() {
            if (_c != null) {
                _c.pathTools.unplug();
                self.canvas.removeElement(_c);
            }
            _drawing = false;
            controls = [];
            path = [];
            _c = null;
            state = 'init';
        };

        var _finishCallBack = null;
        self.onFinish = function(finishCallBack ) {
            _finishCallBack = finishCallBack;
            if (typeof _finishCallBack != 'function') {
                _finishCallBack = function(){};
            }
        };
        var PathToolManger = function(pathEl) {
            this.controls = [];
            this.unplug = function(){
                for (var i = 0; i < this.controls.length; i++) {
                    var control = this.controls[i];
                    control.destroy();
                }
                this.controls = [];
            };
            this.plug = function(){// TODO:创建新的路径工具
                var path = pathEl.attr('path');
                this.controls = [];
                for (var i = 0; i < path.length; i++) {
                    var p = path[i];
                    if (p[0] == 'C') {
                        this.controls.push(new PathTool(p[5], p[6], p[3], p[4], i, pathEl));
//                    } else if (path[i + 1] != undefined && path[i + 1][0] == 'C') {
//                        this.controls.push(new PathTool(p[1], p[2], path[i + 1][1], path[i + 1][2], i, pathEl));
                    }
                }
            };
        };
        var PathTool = function(x, y, ax, ay, index, pathEl){
            var pathEl = pathEl;
            var _path = [["M", x * 2 - ax, y * 2 - ay],["L", ax, ay]];
            var center = {
                x: x,
                y: y
            };
            self.paper.setStart();
            var _line = self.paper.path(_path).attr({stroke: "#CCCCCC", 'stroke-width':2, "stroke-dasharray": "-"}).data('temp', true);
            var _centerCircle = self.paper.circle(x, y, 5).attr(discattr).data('temp', true);// 中心点
            var _circle1 = self.paper.circle(x * 2 - ax, y * 2 - ay, 5).attr(discattr).data('temp', true);// 端点
            var _circle2 = self.paper.circle(ax, ay, 5).attr(discattr).data('temp', true);// 端点
            var set = self.paper.setFinish();

            _centerCircle.update = function (x, y) {// FIXME:
                center.x = this.attr("cx") + x;
                center.y = this.attr("cy") + y;

                _path[1][1] += x;
                _path[1][2] += y;
                _path[0][1] += x;
                _path[0][2] += y;
                _line.attr({path: _path});

                _centerCircle.attr({cx: center.x, cy: center.y});
                _circle1.attr({cx:_path[0][1], cy: _path[0][2]});
                _circle2.attr({cx:_path[1][1], cy: _path[1][2]});

                updatePath();
            };

            _circle1.update = function (x, y) {// FIXME:
                _path[1][1] -= x;
                _path[1][2] -= y;
                _path[0][1] += x;
                _path[0][2] += y;

                _line.attr({path: _path});

                _circle1.attr({cx:_path[0][1], cy: _path[0][2]});
                _circle2.attr({cx:_path[1][1], cy: _path[1][2]});

                updatePath();
            };
            _circle2.update = function (x, y) {// FIXME
                _path[1][1] += x;
                _path[1][2] += y;
                _path[0][1] -= x;
                _path[0][2] -= y;

                _line.attr({path: _path});

                _circle1.attr({cx:_path[0][1], cy: _path[0][2]});
                _circle2.attr({cx:_path[1][1], cy: _path[1][2]});

                updatePath();
            };

            set.drag(function(dx, dy) {// FIXME
                this.update(dx - (this.dx || 0), dy - (this.dy || 0));
                this.dx = dx;
                this.dy = dy;
            }, function(){
                this.dx = this.dy = 0;
            });

            var updatePath = function(){
                var p = pathEl.attr('path');
//                p[index][5] = center.x;
//                p[index][6] = center.y;
                var pref = p[index];
                var next = p[index + 1];
                if (index == 0) {// path start pref[0] == 'M'
                    p[index][1] = center.x;
                    p[index][2] = center.y;
                } else {
                    p[index][5] = center.x;
                    p[index][6] = center.y;
                }

                if (pref[1] == pref[3] && pref[2] == pref[4]) {// firstC
                    pref[1] = _path[1][1];// 对应circle2的中心点
                    pref[2] = _path[1][2];
                    if (next != undefined && next[0] == 'C') {
                        if (next[1] == next[3] && next[2] == next[4]) {
                            next[1] = _path[0][1];// 对应circle1的中心点
                            next[2] = _path[0][2];
                        } else {
                            next[3] = _path[0][1];// 对应circle1的中心点
                            next[4] = _path[0][2];
                        }
                    }
                }else {// secondC
                    if (pref[0] == 'C') {
                        pref[3] = _path[1][1];// 对应circle2的中心点
                        pref[4] = _path[1][2];
                    }
                    if (next != undefined && next[0] == 'C') {
                        if (next[1] == next[3] && next[2] == next[4]) {
                            next[3] = _path[0][1];// 对应circle1的中心点
                            next[4] = _path[0][2];
                        } else {
                            next[1] = _path[0][1];// 对应circle1的中心点
                            next[2] = _path[0][2];
                        }
                    }
                }

                pathEl.attr('path', p);
            }

            this.destroy = function(){
                _line.remove();
                _centerCircle.remove();
                _circle1.remove();
                _circle2.remove();
            };
            this.update = function(x, y, i1, i2){
                _path[1][1] = x;
                _path[1][2] = y;
                _path[0][1] = center.x * 2 - x;
                _path[0][2] = center.y * 2 - y;
                _line.attr({path: _path});
//                _circle1.attr({cx:x, cy:y});

                _circle1.attr({cx:_path[0][1], cy: _path[0][2]});
                _circle2.attr({cx:_path[1][1], cy: _path[1][2]});

                if (i1 != undefined && i2 != undefined) {
                    path[index][i1] = x;
                    path[index][i2] = y;
                    _c.attr({path: path});
                }
            };

        };

        self.mousedown = function(e) {
            _drawing = true;

            mousedown = true;
            curveStart  = false;

            var x = self.canvas.getZoomPosX(e.pageX);
            var y = self.canvas.getZoomPosY(e.pageY);

            if(state == 'init') {
                path.push(["M", x, y]);
                self.canvas.pathToolsUnplug();
                _c = self.paper.path().attr({path: path}).attr(self.canvas.attrChanged());
                _c.pathTools = new PathToolManger(_c);
                controls = _c.pathTools.controls;
            } else if (state == 'curveEnd' && _c != null) {
                _c.pathTools.controls.push(new PathTool(x, y, x, y, path.length - 1, _c));
            }
        };

        var state = 'init';// curveStart, curveEnd, curveStart2, curve2End, line, initCurve

        self.mouseup = function(e) {
            if (_drawing && _c != null) {
                e.stopPropagation();
                mousedown = false;
                var x = self.canvas.getZoomPosX(e.pageX);
                var y = self.canvas.getZoomPosY(e.pageY);
                var p = path[path.length - 1];
                if (state == 'init' || state == 'line') {
                    path.push(["L", x, y]);
                    _c.attr({path: path});

                    state = 'line';
                } else if (state == 'initCurve') {
                    state = 'curveEnd';
                    // 获取上一条曲线的结束点坐标
                    var p = path[path.length - 1];// M
                    x = p[1] * 2 - x;
                    y = p[2] * 2 - y;

                    path.push(['C', x, y, x, y, x,y]);
                    _c.attr({path: path});
                } else if (state == 'curveStart' || state == 'curveStart2') {
                    state = 'curveEnd';
                    // 获取上一条曲线的结束点坐标
                    var p = path[path.length - 1];
                    x = p[5] * 2 - x;
                    y = p[6] * 2 - y;

                    path.push(['C', x, y, x, y, x,y]);
                    _c.attr({path: path});
                } else if (state == 'curveEnd') {
                    state = 'line';
                    path.push(["L", x, y]);
                    _c.attr({path: path});
                }

            }
        };

        self.mousemove = function(e, sketchpad) {
            if (_drawing && _c != null) {
                var x = self.canvas.getZoomPosX(e.pageX);
                var y = self.canvas.getZoomPosY(e.pageY);
                if (mousedown) {
                    //console.log(_c.attr("path"));
                    if (state == 'init') {// 初始化时直接进行拖动
                        controls.push(new PathTool(x, y, x, y, path.length - 1, _c));
                        state = 'initCurve';
                    } else if (state == 'initCurve') {
                        controls[controls.length - 1].update(x, y);
                    } else if (state == 'line') {
                        //console.log(path);
                        path.pop();
                        path.push(['C', x, y, x, y, x,y]);
                        _c.attr({path: path});
                        controls.push(new PathTool(x, y, x, y, path.length - 1, _c));
                        state = 'curveStart';
                    } else if (state == 'curveEnd') {
                        state = 'curveStart2';// 连续绘制曲线
                        controls[controls.length - 1].update(x, y, 3, 4);
                    } else if (state == 'curveStart') {
                        controls[controls.length - 1].update(x, y, 1, 2);
                    } else if (state == 'curveStart2') {
                        controls[controls.length - 1].update(x, y, 3, 4);
                    }

                } else if (state == 'curveEnd') {// 实时更新曲线后半部分
                    var p = path[path.length - 1];
                    p[5] = x;
                    p[6] = y;
                    _c.attr({path:path});
                } else {// line
                    var p = path[path.length - 1];
                    path[path.length - 1][1] = self.canvas.getZoomPosX(e.pageX);
                    path[path.length - 1][2] = self.canvas.getZoomPosY(e.pageY);
                    _c.attr({path:path});
                }
            }
        };

        self.dblclick = function(e) {
            if (_c != null) {
                path.pop();
                path.pop();
                _c.attr({path:path});
                _finishCallBack(_c);
            }
            _drawing = false;
            _c = null;
            controls = [];
            path = [];
            state = 'init';
        }
    };

    var LineTool = function(canvas ) {
        var self = this;
        self.canvas = canvas;
        self.paper = canvas.paper();
        var _canvas;

        // Drawing state
        var _drawing = false;
        var _c = null;
        var _width = 5;
        var x, y;
        var path = null;

        self.abort = function(canvas) {
            if (_c != null) {
                canvas.removeElement(_c);
            }
            _drawing = false;
            _c = null;
        };

        var _finishCallBack = null;
        self.onFinish = function(finishCallBack ) {
            _finishCallBack = finishCallBack;
            if (typeof _finishCallBack != 'function') {
                _finishCallBack = function(){};
            }
        };

        self.mousedown = function(e, canvas) {
            _canvas = canvas;
            _drawing = true;

            x = self.canvas.getZoomPosX(e.pageX);
            y = self.canvas.getZoomPosY(e.pageY);

            if (_c == null) {
                path = [];
                path.push(["M", x, y]);
                path.push(["L", x, y]);
                _c = canvas.paper().path().attr({path: path}).attr(canvas.attrChanged());
            }
        };

        self.mouseup = function(e, sketchpad) {

            if (_c != null) {
                e.stopPropagation();
                var ax = self.canvas.getZoomPosX(e.pageX);
                var ay = self.canvas.getZoomPosY(e.pageY);

                if (Math.abs(ax - x) > _width || Math.abs(ay - y) > _width) {
                    _finishCallBack(_c);
                } else {
                    _c.remove();
                }
            }
            _drawing = false;
            path = null;
            _c = null;

        };

        self.mousemove = function(e, sketchpad) {
            if (_drawing == true) {
                path[path.length - 1][1] = self.canvas.getZoomPosX(e.pageX);
                path[path.length - 1][2] = self.canvas.getZoomPosY(e.pageY);
                //var path = [["M", x, y], ["L", ax, ay]];
                _c.attr({path:path});
            }
        };

    };

})(window.Raphael);
